{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# How to access the RunnableConfig from a tool\n",
        "\n",
        "```{=mdx}\n",
        ":::info Prerequisites\n",
        "\n",
        "This guide assumes familiarity with the following concepts:\n",
        "\n",
        "- [LangChain Tools](/docs/concepts/tools)\n",
        "- [Custom tools](/docs/how_to/custom_tools)\n",
        "- [LangChain Expression Language (LCEL)](/docs/concepts/lcel)\n",
        "\n",
        ":::\n",
        "```\n",
        "\n",
        "Tools are runnables, and you can treat them the same way as any other runnable at the interface level - you can call `invoke()`, `batch()`, and `stream()` on them as normal. However, when writing custom tools, you may want to invoke other runnables like chat models or retrievers. In order to properly trace and configure those sub-invocations, you'll need to manually access and pass in the tool's current [`RunnableConfig`](https://api.js.langchain.com/interfaces/langchain_core.runnables.RunnableConfig.html) object.\n",
        "\n",
        "This guide covers how to do this for custom tools created in different ways.\n",
        "\n",
        "## From the `tool` method\n",
        "\n",
        "Accessing the `RunnableConfig` object for a custom tool created with the [`tool`](https://api.js.langchain.com/functions/langchain_core.tools.tool-1.html) helper method is simple - it's always the second parameter passed into your custom function. Here's an example:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "metadata": {},
      "outputs": [],
      "source": [
        "import { z } from \"zod\";\n",
        "import { tool } from \"@langchain/core/tools\";\n",
        "import type { RunnableConfig } from \"@langchain/core/runnables\";\n",
        "\n",
        "const reverseTool = tool(\n",
        "  async (input: { text: string }, config?: RunnableConfig) => {\n",
        "    const originalString = input.text + (config?.configurable?.additional_field ?? \"\");\n",
        "    return originalString.split(\"\").reverse().join(\"\");\n",
        "  }, {\n",
        "    name: \"reverse\",\n",
        "    description: \"A test tool that combines input text with a configurable parameter.\",\n",
        "    schema: z.object({\n",
        "      text: z.string()\n",
        "    }),\n",
        "  }\n",
        ");"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Then, if we invoke the tool with a `config` containing a `configurable` field, we can see that `additional_field` is passed through correctly:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "321cba\n"
          ]
        }
      ],
      "source": [
        "await reverseTool.invoke(\n",
        "  {text: \"abc\"}, {configurable: {additional_field: \"123\"}}\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Next steps\n",
        "\n",
        "You've now seen how to configure and stream events from within a tool. Next, check out the following guides for more on using tools:\n",
        "\n",
        "- Pass [tool results back to a model](/docs/how_to/tool_results_pass_to_model)\n",
        "- Building [tool-using chains and agents](/docs/how_to#tools)\n",
        "- Getting [structured outputs](/docs/how_to/structured_output/) from models"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "TypeScript",
      "language": "typescript",
      "name": "tslab"
    },
    "language_info": {
      "codemirror_mode": {
        "mode": "typescript",
        "name": "javascript",
        "typescript": true
      },
      "file_extension": ".ts",
      "mimetype": "text/typescript",
      "name": "typescript",
      "version": "3.7.2"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 2
}